<?php
namespace com\rs\dns\service;

use com\rs\dns\constant\ConfigConstant;
use com\rs\dns\constant\RecordConstant;
use com\rs\dns\constant\RecordUrlConst;
use com\rs\dns\controller\api\vo\RecordQuery;
use com\rs\dns\controller\api\vo\UrlForm;
use com\rs\dns\controller\api\vo\UrlInfo;
use com\rs\dns\exception\BaException;
use com\rs\dns\repository\RrRepository;
use com\rs\dns\repository\UrlRepository;
use restphp\biz\PageParam;
use restphp\utils\RestClassUtils;
use restphp\utils\RestStringUtils;

/**
 * Class UrlService
 * @package com\rs\dns\service
 */
final class UrlService {
    /**
     * 获取记录管理列表.
     * @param RecordQuery $recordQuery
     * @param PageParam $pageParam
     * @param string $username
     * @return \restphp\biz\RestPageReturn
     */
    public static function getManageList($recordQuery, $pageParam, $username = '') {
        $arrRule = array(
        );
        if (!RestStringUtils::isBlank($recordQuery->getDomain())) {
            $arrRule['b.origin'] = $recordQuery->getDomain() . ".";
        }
        if (!RestStringUtils::isBlank($recordQuery->getUsername())) {
            $arrRule['b.username'] = $recordQuery->getUsername();
        }
        if (!RestStringUtils::isBlank($username)) {
            $arrRule['b.username'] = $username;
        }

        $arrParams = array(
            'table' => ' url a left join soa b on a.zone=b.id left join net c on a.netid=c.id ',
            'output' => ' a.*, b.origin, b.username, c.netname ',
            'rule' => $arrRule,
            'page_param' => $pageParam,
            'order' => ' order by a.domain '
        );
        $urlRepository = new UrlRepository();
        $pageResult = $urlRepository->getPageReturn($arrParams);
        if ($pageResult->getTotal() > 0) {
            $arrList = array();
            foreach ($pageResult->getItems() as $arrItem) {
                $name = str_replace($arrItem['origin'], '', $arrItem['domain']);
                if (!RestStringUtils::isBlank($name)) {
                    $name = substr($name, 0, strlen($name) - 1);
                }
                $arrItem['name'] = $name;
                $arrList[] = RestClassUtils::copyFromArr(new UrlInfo(), $arrItem);
            }
            $pageResult->setItems($arrList);
        }
        return $pageResult;
    }

    /**
     * 添加记录值.
     * @param UrlForm $urlForm
     * @throws \restphp\exception\RestException
     */
    public static function add($urlForm) {
        $rrRepository = new RrRepository();
        //是否存在相同的RR
        $domainInfo = DomainService::getInfoByDomain($urlForm->getOrigin() . ".");
        $arrExistsRule = array(
            'zone' => $domainInfo['id'],
            'name' => $urlForm->getName(),
            'type' => 'A',
            'netid' => $urlForm->getNetid()
        );
        $arrExists = $rrRepository->findOne($arrExistsRule);
        if (!empty($arrExists)) {
            throw new BaException(RecordConstant::RECORD_SAME_EXISTS);
        }

        $urlRepository = new UrlRepository();
        $arrAdd = RestClassUtils::beanToArr($urlForm, false);
        unset($arrAdd['origin']);
        unset($arrAdd['name']);
        $arrAdd['domain'] = $urlForm->getName() . (RestStringUtils::isBlank($urlForm->getName()) ? '' : '.') . $domainInfo['origin'];
        $arrAdd['zone'] = $domainInfo['id'];

        //是否存在相同url
        $arrExistsUrlRule = array(
            'domain' => $arrAdd['domain']
        );
        $arrExistsUrl = $urlRepository->findOne($arrExistsUrlRule);
        if (!empty($arrExistsUrl)) {
            throw new BaException(RecordUrlConst::URL_SAME_EXISTS);
        }

        //添加RR
        $arrForm = array(
            'zone' => $domainInfo['id'],
            'name' => $urlForm->getName(),
            'type' => 'A',
            'netid' => $urlForm->getNetid(),
            'data' => ConfigService::getConfigValue(ConfigConstant::CODE_URL_SERVER_IP),
            'aux' => 10,
            'ttl' => 600,
            'balance' => 0,
            'isurl' => 1
        );
        $rrRepository->insert($arrForm);
        $rrId = $rrRepository->last_insert_id();

        //更新soa版本
        DomainService::updateSerial($domainInfo['id']);

        $arrAdd['rrid'] = $rrId;

        $urlRepository->insert($arrAdd);
        //数据订阅
        $readData = RestClassUtils::beanToArr($urlForm, false);
        $readData['id'] = $urlRepository->last_insert_id();
        ForeignService::post('/urls', $readData);
    }

    /**
     * 修改记录.
     * @param int $id
     * @param UrlForm $urlForm
     * @throws \restphp\exception\RestException
     */
    public static function modify($id, $urlForm) {
        $rrRepository = new RrRepository();
        $domainInfo = DomainService::getInfoByDomain($urlForm->getOrigin() . ".");

        //url是否存在
        $urlRepository = new UrlRepository();
        $arrUrlQueryRule = array(
            'id' => $id
        );
        $arrUrl = $urlRepository->findOne($arrUrlQueryRule);
        if (null == $arrUrl || empty($arrUrl)) {
            throw new BaException(RecordUrlConst::URL_DATA_NOT_EXISTS);
        }

        $arrUpdate = RestClassUtils::beanToArr($urlForm, false);
        unset($arrUpdate['origin']);
        unset($arrUpdate['name']);
        $arrUpdate['domain'] = $urlForm->getName() . (RestStringUtils::isBlank($urlForm->getName()) ? '' : '.') . $domainInfo['origin'];

        //是否存在相同url
        $arrExistsUrlRule = array(
            'domain' => $arrUpdate['domain'],
            'id' => array(' id!=' . strval($id))
        );
        $arrExistsUrl = $urlRepository->findOne($arrExistsUrlRule);
        if (!empty($arrExistsUrl)) {
            throw new BaException(RecordUrlConst::URL_SAME_EXISTS);
        }

        //是否存在相同的解析
        $arrExistsRule = array(
            'zone' => $domainInfo['id'],
            'name' => $urlForm->getName(),
            'type' => 'A',
            'netid' => $urlForm->getNetid(),
            'id' => array(' id!= ' . $arrUrl['rrid'])
        );
        $arrExists = $rrRepository->findOne($arrExistsRule);
        if (!empty($arrExists)) {
            throw new BaException(RecordConstant::RECORD_SAME_EXISTS);
        }

        // 删除RR
        $arrRrDeleteRule = array(
            'id' => $arrUrl['rrid']
        );
        $rrRepository->delete($arrRrDeleteRule);

        // 添加RR
        $arrForm = array(
            'zone' => $domainInfo['id'],
            'name' => $urlForm->getName(),
            'type' => 'A',
            'netid' => $urlForm->getNetid(),
            'data' => ConfigService::getConfigValue(ConfigConstant::CODE_URL_SERVER_IP),
            'aux' => 10,
            'ttl' => 600,
            'balance' => 0,
            'isurl' => 1
        );
        $rrRepository->insert($arrForm);
        $rrId = $rrRepository->last_insert_id();
        $arrUpdate['rrid'] = $rrId;

        //更新soa版本
        DomainService::updateSerial($domainInfo['id']);

        //更新转发数据
        $arrRule = array(
            'id' => $id
        );
        $urlRepository->update($arrUpdate, $arrRule);

        //数据订阅
        ForeignService::put("/urls/{$id}", RestClassUtils::beanToArr($urlForm, false));
    }

    /**
     * 删除。
     * @param $id
     * @throws \restphp\exception\RestException
     */
    public static function delete($id) {
        $arrRule = array(
            'id' => $id
        );
        $urlRepository = new UrlRepository();

        //是否存在URL
        $arrUrl = $urlRepository->findOne($arrRule);
        if (null == $arrUrl || empty($arrUrl)) {
            throw new BaException(RecordUrlConst::URL_DATA_NOT_EXISTS);
        }

        // 删除RR
        $arrRrDeleteRule = array(
            'id' => $arrUrl['rrid']
        );
        $rrRepository = new RrRepository();
        $rrRepository->delete($arrRrDeleteRule);
        //更新soa版本
        DomainService::updateSerial($arrUrl['zone']);

        $urlRepository->delete($arrRule);

        //数据订阅
        ForeignService::delete("/urls/{$id}");
    }

    /**
     * 批量删除.
     * @param $arrId
     * @throws \restphp\exception\RestException
     */
    public static function batchDelete($arrId) {
        $urlRepository = new UrlRepository();
        $urlRepository->batchDelete($arrId);

        //数据订阅
        ForeignService::post("/urls/actions/delete", $arrId);
    }

    /**
     * 通过域名删除
     * @param array $arrZoneId
     */
    public static function deleteByZones($arrZoneId) {
        $urlRepository = new UrlRepository();
        $urlRepository->batchDelete($arrZoneId, 'zone');
    }

    /**
     * 旧转发关联域名信息.
     * @throws \restphp\exception\RestException
     */
    public static function changeOld() {
        $urlRepository = new UrlRepository();
        //获取所有未关联域名的解析记录.
        $arrRule = array(
            'zone' => 0
        );
        $arrList = $urlRepository->findAll($arrRule);

        foreach ($arrList as $item) {
            $domain = $item['domain'];
            if (!RestStringUtils::endWith($domain, ".")) {
                $domain .= '.';
            }
            $domainInfo = self::_loopGetDomain($domain);
            if (null == $domainInfo) {
                continue;
            }

            $arrUpdate = array('zone' => $domainInfo['id']);
            $arrUpdateRule = array('id' => $item['ID']);
            $urlRepository->update($arrUpdate, $arrUpdateRule);
        }
    }

    /**
     * 循环查询获取域名信息.
     * @param $domain
     * @return mixed|null
     */
    private static function _loopGetDomain($domain) {
        $domainInfo = DomainService::getInfoByDomain($domain);
        if (null != $domainInfo) {
            return $domainInfo;
        }

        $arrDomain = explode(".", $domain);
        var_dump($arrDomain);
        if (!isset($arrDomain[3])) {
            return null;
        }
        $newDomain = '';
        for ($i = 1; $i < count($arrDomain); $i++) {
            $newDomain .= ($newDomain == '' ? '' : '.') . $arrDomain[$i];
        }
        return self::_loopGetDomain($newDomain);
    }

    /**
     * 是否有转发记录权限.
     * @param $urlId
     * @param $username
     * @return bool
     */
    public static function hadUrl($urlId, $username) {
        $arrParams = array(
            'table' => ' url a left join soa b on a.zone=b.id ',
            'rule' => array(
                'a.id' => $urlId,
                'b.username' => $username
            )
        );
        $urlRepository = new UrlRepository();
        return $urlRepository->count($arrParams) > 0;
    }

    /**
     * 是否有转发记录(S)权限.
     * @param $arrUrlId
     * @param $username
     * @return bool
     */
    public static function hadUrls($arrUrlId, $username) {
        $strRule = '';
        foreach ($arrUrlId as $id) {
            $strRule .= ('' == $strRule ? '' : ',') . '?';
        }
        $arrParams = array(
            'table' => ' url a left join soa b on a.zone=b.id ',
            'rule' => array(
                'a.id' => array(
                    " a.id in ({$strRule}) ",
                    $arrUrlId
                ),
                'b.username' => $username
            )
        );
        $urlRepository = new UrlRepository();
        $total = $urlRepository->count($arrParams);
        return $total == count($arrUrlId);
    }
}